package com.keyingbo.orm.framework.spring;

import com.keyingbo.orm.framework.IEntityStatement;
import com.keyingbo.orm.framework.annotation.EntityStatement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * DAO注解注入实现类。
 * @Auther: KEYB
 * @Date: 2019-4-28 11:18
 * @Description:
 */
public class DaoAnnotationBeanPostProcessor implements BeanFactoryAware, BeanPostProcessor {
    private static final Log log = LogFactory.getLog(DaoAnnotationBeanPostProcessor.class);
    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Package pkg = bean.getClass().getPackage();
        if(pkg != null){
            String name = pkg.getName();
            if(!name.matches("com[.]keyingbo[.].*?[.]service[.]impl")
                    && !name.matches("com[.]keyingbo[.].*?[.]service")
                    && !name.matches("com[.]keyingbo[.].*?[.]service.*?")
            ){
                return bean;
            }
        }
        Field[] fields = bean.getClass().getDeclaredFields();
        for(Field f : fields){
            EntityStatement anno = f.getAnnotation(EntityStatement.class);
            if(anno!=null){
                Class<?> type = f.getType();
                //TODO 可以支持更多方式
                if(type== IEntityStatement.class){
                    Type cls = f.getGenericType();
                    if (cls instanceof ParameterizedType) {
                        ParameterizedType genericSuperclass = (ParameterizedType) cls;
                        Class<?> clsx = (Class<?>) genericSuperclass.getActualTypeArguments()[0];
                        String name = clsx.getSimpleName().toLowerCase()+"_dao";
                        Object daoBean = this.beanFactory.getBean(name);
                        f.setAccessible(true);
                        try {
                            f.set(bean, daoBean);
                        } catch (IllegalArgumentException e) {
                            log.error("非法参数", e);
                        } catch (IllegalAccessException e) {
                            log.error("非法访问", e);
                        }
                    }
                }
            }
        }
        return bean;
    }
}
